xl: vcpu-list command
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 6 Apr 2010 05:54:08 +0000 (06:54 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 6 Apr 2010 05:54:08 +0000 (06:54 +0100)
Signed-off-by: Eric Chanudet <eric.chanudet@citrix.com>
Acked-by: Vincent Hanquez <vincent.hanquez@eu.citrix.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
tools/libxl/libxl.c
tools/libxl/libxl.h
tools/libxl/xl.c

index 0b1b6dba31fcb6acbbcc08cefe20cd34b7b33008..4aa9b9bde4be8422156f534832871b4e6539ae46 100644 (file)
@@ -2221,3 +2221,64 @@ int libxl_button_press(struct libxl_ctx *ctx, uint32_t domid, libxl_button butto
 
     return rc;
 }
+
+int libxl_get_physinfo(struct libxl_ctx *ctx, struct libxl_physinfo *physinfo)
+{
+    xc_physinfo_t xcphysinfo = { 0 };
+    int rc;
+
+    rc = xc_physinfo(ctx->xch, &xcphysinfo);
+    if (rc != 0) {
+        return rc;
+    }
+    physinfo->threads_per_core = xcphysinfo.threads_per_core;
+    physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
+    physinfo->nr_cpus = xcphysinfo.nr_cpus;
+    physinfo->cpu_khz = xcphysinfo.cpu_khz;
+    physinfo->total_pages = xcphysinfo.total_pages;
+    physinfo->free_pages = xcphysinfo.free_pages;
+    physinfo->scrub_pages = xcphysinfo.scrub_pages;
+    return 0;
+}
+
+struct libxl_vcpuinfo *libxl_list_vcpu(struct libxl_ctx *ctx, uint32_t domid,
+                                       int *nb_vcpu, int *cpusize)
+{
+    struct libxl_vcpuinfo *ptr, *ret;
+    xc_domaininfo_t domaininfo;
+    xc_vcpuinfo_t vcpuinfo;
+    xc_physinfo_t physinfo = { 0 };
+
+    if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
+        return NULL;
+    }
+    if (xc_physinfo(ctx->xch, &physinfo) == -1) {
+        return NULL;
+    }
+    *cpusize = physinfo.max_cpu_id + 1;
+    ptr = libxl_calloc(ctx, domaininfo.max_vcpu_id + 1, sizeof (struct libxl_vcpuinfo));
+    if (!ptr) {
+        return NULL;
+    }
+
+    ret = ptr;
+    for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) {
+        ptr->cpumap = libxl_calloc(ctx, (*cpusize + 63) / 64, sizeof (uint64_t));
+        if (!ptr->cpumap) {
+            return NULL;
+        }
+        if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) {
+            return NULL;
+        }
+        if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu, ptr->cpumap, *cpusize) == -1) {
+            return NULL;
+        }
+        ptr->vcpuid = *nb_vcpu;
+        ptr->cpu = vcpuinfo.cpu;
+        ptr->online = !!vcpuinfo.online;
+        ptr->blocked = !!vcpuinfo.blocked;
+        ptr->running = !!vcpuinfo.running;
+        ptr->vcpu_time = vcpuinfo.cpu_time;
+    }
+    return ret;
+}
index 84e412a0c63e41c012ce4271bc01c329cbb8e7ad..64a4fbfd8ec1f913bf715c5ed17423fd44bec7e6 100644 (file)
@@ -360,5 +360,31 @@ typedef enum {
 
 int libxl_button_press(struct libxl_ctx *ctx, uint32_t domid, libxl_button button);
 
+struct libxl_vcpuinfo {
+    uint32_t vcpuid; /* vcpu's id */
+    uint32_t cpu; /* current mapping */
+    uint8_t online:1; /* currently online (not hotplugged)? */
+    uint8_t blocked:1; /* blocked waiting for an event? */
+    uint8_t running:1; /* currently scheduled on its CPU? */
+    uint64_t vcpu_time; /* total vcpu time ran (ns) */
+    uint64_t *cpumap; /* current cpu's affinities */
+};
+
+struct libxl_physinfo {
+    uint32_t threads_per_core;
+    uint32_t cores_per_socket;
+
+    uint32_t nr_cpus;
+    uint32_t cpu_khz;
+
+    uint64_t total_pages;
+    uint64_t free_pages;
+    uint64_t scrub_pages;
+};
+
+int libxl_get_physinfo(struct libxl_ctx *ctx, struct libxl_physinfo *physinfo);
+struct libxl_vcpuinfo *libxl_list_vcpu(struct libxl_ctx *ctx, uint32_t domid,
+                                       int *nb_vcpu, int *cpusize);
+
 #endif /* LIBXL_H */
 
index 8518e8fd0ed4d8237e1365e2f956b95fba9cda86..da758fe2b03015657d7ee74c102e21b35d9a28d2 100644 (file)
@@ -876,6 +876,7 @@ static void help(char *command)
         printf(" cd-eject                      eject a cdrom from a guest's cd drive\n\n");
         printf(" mem-set                       set the current memory usage for a domain\n\n");
         printf(" button-press                  indicate an ACPI button press to the domain\n\n");
+        printf(" vcpu-list                     list the VCPUs for all/some domains.\n\n");
     } else if(!strcmp(command, "create")) {
         printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
         printf("Create a domain based on <ConfigFile>.\n\n");
@@ -933,6 +934,9 @@ static void help(char *command)
         printf("Usage: xl button-press <Domain> <Button>\n\n");
         printf("Indicate <Button> press to a domain.\n");
         printf("<Button> may be 'power' or 'sleep'.\n\n");
+    } else if (!strcmp(command, "vcpu-list")) {
+        printf("Usage: xl vcpu-list [Domain, ...]\n\n");
+        printf("List the VCPUs for all/some domains.\n\n");
     }
 }
 
@@ -1721,6 +1725,144 @@ int main_button_press(int argc, char **argv)
     exit(0);
 }
 
+static void print_vcpuinfo(struct libxl_ctx *ctx, uint32_t domid,
+                           const struct libxl_vcpuinfo *vcpuinfo,
+                           uint32_t nr_cpus)
+{
+    int i, l;
+    uint64_t *cpumap;
+    uint64_t pcpumap;
+
+    /*      NAME  ID  VCPU */
+    printf("%-32s %5u %5u",
+           libxl_domid_to_name(ctx, domid), domid, vcpuinfo->vcpuid);
+    if (!vcpuinfo->online) {
+        /*      CPU STA */
+        printf("%5c %3c%cp ", '-', '-', '-');
+    } else {
+        /*      CPU STA */
+        printf("%5u %3c%c- ", vcpuinfo->cpu,
+               vcpuinfo->running ? 'r' : '-',
+               vcpuinfo->blocked ? 'b' : '-');
+    }
+    /*      TIM */
+    printf("%9.1f  ", ((float)vcpuinfo->vcpu_time / 1e9));
+    /* CPU AFFINITY */
+    pcpumap = nr_cpus > 64 ? -1 : ((1 << nr_cpus) - 1);
+    for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
+        if (*cpumap < pcpumap) {
+            break;
+        }
+        if (nr_cpus > 64) {
+            pcpumap = -1;
+            nr_cpus -= 64;
+        } else {
+            pcpumap = ((1 << nr_cpus) - 1);
+            nr_cpus = 0;
+        }
+    }
+    if (!nr_cpus) {
+        printf("any cpu\n");
+    } else {
+        for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) {
+            pcpumap = *cpumap;
+            for (i = 0; !(pcpumap & 1); ++i, pcpumap >>= 1)
+                ;
+            printf("%u", i);
+            for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap >>= 1)
+                ;
+            if (l < i) {
+                printf("-%u", i);
+            }
+            for (++i; pcpumap; ++i, pcpumap >>= 1) {
+                if (pcpumap & 1) {
+                    printf(",%u", i);
+                    for (l = i, pcpumap = (pcpumap >> 1); (pcpumap & 1); ++i, pcpumap >>= 1)
+                        ;
+                    if (l < i) {
+                        printf("-%u", i);
+                    }
+                    ++i;
+                }
+            }
+            printf("\n");
+            nr_cpus = nr_cpus > 64 ? nr_cpus - 64 : 0;
+        }
+    }
+}
+
+void vcpulist(int argc, char **argv)
+{
+    struct libxl_ctx ctx;
+    struct libxl_dominfo *dominfo;
+    uint32_t domid;
+    struct libxl_vcpuinfo *vcpuinfo;
+    struct libxl_physinfo physinfo;
+    int nb_vcpu, nb_domain, cpusize;
+
+    if (libxl_ctx_init(&ctx, LIBXL_VERSION)) {
+        fprintf(stderr, "cannot init xl context\n");
+        return;
+    }
+    libxl_ctx_set_log(&ctx, log_callback, NULL);
+
+    if (libxl_get_physinfo(&ctx, &physinfo) != 0) {
+        fprintf(stderr, "libxl_physinfo failed.\n");
+        goto vcpulist_out;
+    }
+    printf("%-32s %5s %5s %5s %5s %9s %s\n",
+           "Name", "ID", "VCPU", "CPU", "State", "Time(s)", "CPU Affinity");
+    if (!argc) {
+        if (!(dominfo = libxl_list_domain(&ctx, &nb_domain))) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            goto vcpulist_out;
+        }
+        for (; nb_domain > 0; --nb_domain, ++dominfo) {
+            if (!(vcpuinfo = libxl_list_vcpu(&ctx, dominfo->domid, &nb_vcpu, &cpusize))) {
+                fprintf(stderr, "libxl_list_vcpu failed.\n");
+                goto vcpulist_out;
+            }
+            for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
+                print_vcpuinfo(&ctx, dominfo->domid, vcpuinfo, physinfo.nr_cpus);
+            }
+        }
+    } else {
+        for (; argc > 0; ++argv, --argc) {
+            if (domain_qualifier_to_domid(&ctx, *argv, &domid) < 0) {
+                fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            }
+            if (!(vcpuinfo = libxl_list_vcpu(&ctx, domid, &nb_vcpu, &cpusize))) {
+                fprintf(stderr, "libxl_list_vcpu failed.\n");
+                goto vcpulist_out;
+            }
+            for (; nb_vcpu > 0; --nb_vcpu, ++vcpuinfo) {
+                print_vcpuinfo(&ctx, domid, vcpuinfo, physinfo.nr_cpus);
+            }
+        }
+    }
+  vcpulist_out:
+    libxl_ctx_free(&ctx);
+}
+
+void main_vcpulist(int argc, char **argv)
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("vcpu-list");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    vcpulist(argc - 1, argv + 1);
+    exit(0);
+}
+
 int main(int argc, char **argv)
 {
     if (argc < 2) {
@@ -1762,6 +1904,8 @@ int main(int argc, char **argv)
         main_memset(argc - 1, argv + 1);
     } else if (!strcmp(argv[1], "button-press")) {
         main_button_press(argc - 1, argv + 1);
+    } else if (!strcmp(argv[1], "vcpu-list")) {
+        main_vcpulist(argc - 1, argv + 1);
     } else if (!strcmp(argv[1], "help")) {
         if (argc > 2)
             help(argv[2]);
@@ -1773,4 +1917,3 @@ int main(int argc, char **argv)
         exit(1);
     }
 }
-